#ifndef SOCKETS_IMP_HPP
#define SOCKETS_IMP_HPP

#include "sockets.hpp"

#ifdef SCK_WIN32

#ifdef _MSC_VER
#pragma comment(lib, "ws2_32.lib")
#endif

#include <winsock.h>
typedef int socklen_t;

namespace
{
	
	inline int getsyserror() { return WSAGetLastError(); }
	
	int const SCKER_INPROGRESS = WSAEINPROGRESS;
	int const SCKER_WOULDBLOCK = WSAEWOULDBLOCK;
	int const SCKER_ADDRESSINUSE = WSAEADDRINUSE;
	
	int error_ret = SOCKET_ERROR;
	inline bool isError( int res ) { return res == error_ret || res < 0; }
	
	inline int closeSocket( void* handler )
	{
		return closesocket( reinterpret_cast<SOCKET>(handler) );
	}
	
	inline SOCKET toNative( void* handler )
	{
		return reinterpret_cast<SOCKET>(handler);
	}
	
	inline void* fromNative( SOCKET handler )
	{
		return reinterpret_cast<void*>( handler );
	}
}

#else

namespace
{
	inline int getsyserror() { return errno; }
	int const SCKER_INPROGRESS = EINPROGRESS;
	int const SCKER_WOULDBLOCK = EWOULDBLOCK;
	int const SCKER_ADDRESSINUSE = EADDRINUSE;
	
	int error_ret = -1;
	inline isError( int res ) { return res == error_ret || res < 0; }
	
	inline int closeSocket( int handler )
	{
		return close( handler );
	}
	
	inline int toNative( int handler )
	{
		return handler;
	}
	
	inline int fromNative( int handler )
	{
		return handler;
	}
}

#endif

class SocketData
{
	friend class UdpSocket;
	friend class TcpSocket;
	
	struct Flags{
	
	static const int NoFlags = 0;
	static const int ErrorOccurred = ( 1 << 0 );
	static const int Connecting    = ( 1 << 1 );
	static const int Connected     = ( 1 << 2 );
	static const int TimedOut      = ( 1 << 3 );
	};
	
	SocketData( int flags_ = 0 ) : flags(flags_), refCount(0) {}
	
	void setFlags( int flags_ ) { flags |= flags_; }
	void clearFlags( int flags_ ) { flags &= ~flags_; }

	#ifdef SCK_WIN32
	void* handler;
	#else
	int handler;
	#endif
	int flags;
	int refCount;
};

#endif //SOCKETS_IMP_HPP
